home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / MacStarter Pascal 1.0 / xWindows definition files / xControlDecoration.p < prev    next >
Encoding:
Text File  |  1993-05-13  |  26.7 KB  |  902 lines  |  [TEXT/PJMM]

  1. unit xControlDecoration;
  2.  
  3. { "Controls" in Macintosh lingo refer to things like scroll bars, buttons, check }
  4. { boxes and radio buttons.   This unit implements all these classes of controls as }
  5. { xWindowDecorations.  }
  6.  
  7. interface
  8.  
  9. uses
  10.     xWindow;
  11.  
  12. type
  13.     xControlDecoration = object(xWindowDecoration)
  14.              { An abstract class providing the common protocol for all control decorations }
  15.              { NOTE: among the useful stuff inherited from xWindowDecoration is the }
  16.              { instance variable  itsWindow, which tells you which xWindow the control }
  17.              { is installed into. }
  18.             theControl: controlHandle;  { Macintosh control data }
  19.             trueWidth, trueHeight: integer;  { actual size of the control }
  20.             procedure makeInactive;
  21.              { "Grays out" the control , so clicking on it will have no effect }
  22.             procedure makeActive;
  23.             { makes a grayed out control active again }
  24.             procedure init;  { This and remaining procedures just redefine procedures from }
  25.             override;              { class xWindowDecoration (in unit xWindow.p) }
  26.             procedure kill;
  27.             override;
  28.             procedure doActivate (active: boolean);
  29.             override;
  30.             procedure adjustSize;
  31.             override;
  32.             procedure show;
  33.             override;
  34.             procedure hide;
  35.             override;
  36.         end;
  37.  
  38.     xButton = object(xControlDecoration)
  39.           { A push button control.  When the user clicks on the button, the procedure }
  40.           { HandleClick is called.  In this class, HandleClick does nothing.  To make it }
  41.           { do something, you should define a subclass in which you override the }
  42.           { HandleClick method.  You do not necessarily have to do this for each button }
  43.           { you want, since you can determine easily which button was pressed (by }
  44.           { refering to the variable SELF) and which window it was in. }
  45.             procedure SetUp (win: xWindow;
  46.                                         name: string;
  47.                                         theLeft, theTop, theWidth, theHeight: integer);
  48.           { installes a button with the given name in the given window.  The name is }
  49.           { displayed on the button.  If the character "\" occurs in the name, it is treated }
  50.           { as a line feed, allowing you to have multi-line names.   The parameters }
  51.           { theLeft,...,theHeight determine the size and location of the button, as }
  52.           { discussed in the comments on procedure xWindowDecoration.Install in }
  53.           { unit xWindopw.p.  However, if the resulting size is not large enough to }
  54.           { display the button's name, the size will be increased as necessary .  (Thus, }
  55.           { for example, to get a button in which the name just fits nicely, you can }
  56.           { pass valued of 1 for theWidth and theHeight.) }
  57.             procedure HandleClick;
  58.           { Called when the user clicks on the button; by default, does nothing }
  59.             procedure Press;
  60.           { simulates pressing the button, exactly as if the user had clicked on it.  This  }
  61.           { includes briefly hiliting the button and calling HandleClick.  This will have }
  62.           { no effect, of course, if the button is grayed out. }
  63.             procedure SetName (name: string);
  64.           { Change the name of the button.  This might force the size of th button to increase, }
  65.           { if there is not room for the new name in the current button.  Note,  however, that }
  66.           { calling this procedure will never decrease the size of the button. }
  67.             procedure doClick (localPt: point;
  68.                                         modifiers: longint);  { handles user click }
  69.             override;
  70.         end;
  71.  
  72.     xDefaultButton = object(xButton)
  73.             { Similar to a button except: (1) A thick outline is drawn around the button, and }
  74.             { (2) when the user presses Return or Enter, it will have the same effect as }
  75.             { clicking on this button.  You should not have more than one of these in a window }
  76.             { If you do, a Return or Enter will press the one most recently installed. }
  77.             { All comments about xButtons apply. }
  78.             procedure init;
  79.             override;
  80.             procedure adjustSize;
  81.             override;
  82.             procedure doCr (ch: char);
  83.             override;
  84.             procedure doDraw;
  85.             override;
  86.         end;
  87.  
  88.     xScrollBar = object(xControlDecoration)
  89.             { A standard scroll bar.  }
  90.             linesPerPage: integer;  { number of units by which the scroll bar will scroll }
  91.                                             { when the user clicks in the gray area of the scroll bar }
  92.             savedMax, savedVal: integer;  { save value while the scroll bar is  inactive }
  93.             procedure SetUp (win: xWindow;
  94.                                         theLeft, theTop, theWidth, theHeight: integer);
  95.             { Install a scroll bar in the specified window.  The meanings of the other }
  96.             { parameters define the location and size of the scroll bar, as described in }
  97.             { the comments on procedure xWindowDecoration.Install in unit xWindow.p. }
  98.             {  Several additional comments apply to scroll bars:  Ordinarily, you will }
  99.             { set either the height or the width of the scroll bar to 15 (although some }
  100.             { other values are useable, such as 10 and 30).  The other dimension should }
  101.             { be at least four times as large.   When the scroll bar is installed or resized, }
  102.             { a restriction that both dimensions be >= 10, and that one dimension be }
  103.             { at least 4 times as large as the other is enforced, and the size will be }
  104.             { changed if necesary.  Whether the scroll bar is vertical or horizontal depends }
  105.             { only on which dimension is greater. }
  106.             procedure HandleScroll (changeInVal: integer);
  107.             { This is called whenever the user changes the value of the scroll bar.  It is }
  108.             { called repeatedly if the user holds down the mouse.  The parameter specified }
  109.             { the change in the scroll value, but you can easily get the current value if }
  110.             { you like, by calling GetVal.  The default method defined for this class does }
  111.             { nothing.  You can override it if you need to in a subclass. }
  112.             procedure SetMax (newMax: integer);
  113.             procedure SetVal (newVal: integer);
  114.             function GetVal: integer;
  115.             function GetMax: integer;
  116.             { These four procedures are used to set and inspect the scroll value and the }
  117.             { maximum scroll value.  The value can go from 0 to the specified maximum. }
  118.             { If the maximum is 0, then the scroll bar is essentially useless; you will }
  119.             { set a maximum value immediately after calling SetUp.  NOTE:  SetVal }
  120.             { does NOT call HandleScroll. }
  121.             procedure SetLinesPerPage (lines: integer);
  122.             { Determines how many units the scroll bar scrolls when the user clicks in }
  123.             { the scroll bar's gray area;  initialized to 1. }
  124.             procedure makeActive;  { remaining procedures just override inherited }
  125.             override;                           { methods, as appropriate for scroll bars. }
  126.             procedure makeInactive;
  127.             override;
  128.             procedure doClick (localPt: point;
  129.                                         modifiers: longint);
  130.             override;
  131.             procedure adjustSize;
  132.             override;
  133.         end;
  134.  
  135.     xCheckBox = object(xControlDecoration)
  136.            { Implements a Check box, which has two states, checked and unchecked; }
  137.            { the user toggles between these states by clicking on the box, or on its }
  138.            { name, which is displayed to the right of the box. }
  139.             procedure SetUp (win: xWindow;
  140.                                         name: string;
  141.                                         theLeft, theTop: integer);
  142.            { Installs the chek box at the given position.  The size of this control cannot }
  143.            { be changed.  The name is displayed to the right of the box.  If the name includes }
  144.            { the character "\", it is interpreted as a line feed, allowing you to have multi- }
  145.            { line box labels.  The box is unchecked when is is first installed. }
  146.             procedure check;
  147.            { set the box to the Checked state }
  148.             procedure unCheck;
  149.            { set the box the Unchecked state }
  150.             function checked: boolean;
  151.            { returns TRUE if the box is Checked, FALSE if not }
  152.             procedure HandleClick;
  153.            { Called when the user clicked on the box; ordinarily, nothing needs to be done, }
  154.            { and that is what this default method does.  You can call function checked when }
  155.            { you need to determine if the box is checked.  However, you can override this }
  156.            { method when you want to react immediately to the user's clicking the box. }
  157.             procedure doClick (localPt: point;
  158.                                         modifiers: longint);  { react to user click }
  159.             override;
  160.         end;
  161.  
  162.     xRadioGroup = object
  163.            { A radio button is similar to a check box, in that it can have two states, but it }
  164.            { is represented by a circle that can be filled in or not.  Radio buttons should }
  165.            { always occur in groups of two or more, and exactly one of the buttons in }
  166.            { a group should be on at any given time. }
  167.            { This class implements vertically arranged groups of up to 10 radio buttons. }
  168.            { Note that if you want to activate and inactivate individual buttons, you will }
  169.            { have to send messages to them individually. }
  170.             theButtons: array[1..10] of xRadioButton;   { the buttons in the group }
  171.             buttonCount: 1..10;   { number of buttons }
  172.             selected: 1..10;   { which of the buttons is currently selected }
  173.             procedure SetUp (win: xWindow;
  174.                                         name: string;
  175.                                         theLeft, theTop: integer);
  176.            { Installs a radio group in the window at the specified location; it is not possible }
  177.            { to change the size of a radio group.  The "name" parameter must contain the }
  178.            { labels for all the buttons in the group, separated by backslashes (\). }
  179.            { Initially, button 1 is selected. }
  180.             procedure select (buttonNum: integer);
  181.            { Select the specified button in the group. Note that although the user cannot }
  182.            { select a grayed out button by clicking on it, you can select it with this procedure. }
  183.             function selectedButton: integer;
  184.            { returns the number of the button in the group that is currently selected. }
  185.             procedure HandleChangeOfSelection;
  186.            { Called when the user changes the selected button.  This default method }
  187.            { does nothing, which is usually the desired behaviour. }
  188.             procedure hide;
  189.            { Hides the entire group of button }
  190.             procedure show;
  191.            { Shows all the buttons }
  192.         end;
  193.  
  194.     xRadioButton = object(xCheckBox)
  195.           { an individual radio button.  This class should not ordinarily be used directly. }
  196.            { If it is, it will act just like a check box, and will just look different. }
  197.             itsGroup: xRadioGroup;
  198.             numInGroup: integer;
  199.             procedure SetUp (win: xWindow;
  200.                                         name: string;
  201.                                         theLeft, theTop: integer);
  202.             override;
  203.             procedure doClick (localPt: point;
  204.                                         modifiers: longint);
  205.             override;
  206.         end;
  207.  
  208.  
  209.     xEmptyButton = object(xWindowDecoration)
  210.          { the intent of this class is to provide something like an invisible button that }
  211.          { can be placed over some existing graphics, such as an xIcon;  the button created }
  212.          { in this way will act pretty much like an ordinary button and is used in the }
  213.          { same way.  Since it is not really a control, it does not respond to all the methods }
  214.          { defined for xControlDecorations. }
  215.             procedure SetUp (win: xWindow;
  216.                                         theLeft, theRight, theWidth, theHeight: integer);
  217.          { creates the button and installs it in the window win; the remaining parameters }
  218.          { have their usual meaning (see comment on xButton.SetUp) }
  219.             procedure HandleClick;
  220.          { This is called when the user clicks the button; to use a button, you will }
  221.          { ordinarily create a sub-class and override this method. }
  222.             procedure Press;
  223.          { simulates a user press of the button, including briefly hiliting the button and }
  224.          { calling procedure HandleClick }
  225.             procedure doClick (localPt: point;
  226.                                         modifiers: longint);
  227.             override;
  228.         end;
  229.  
  230.     xFramedEmptyButton = object(xEmptyButton)
  231.        { identical to xEmptyButton, except a 1-pixel wide border is drawn around the button }
  232.             procedure doDraw;
  233.             override;
  234.         end;
  235.  
  236.  
  237. implementation
  238.  
  239. procedure xControlDecoration.makeInactive;
  240.     begin
  241.         if theControl <> nil then
  242.             if not grayedOut then begin
  243.                     grayedOut := true;
  244.                     wantsClick := false;
  245.                     HiliteControl(theControl, 255);
  246.                 end;
  247.     end;
  248.  
  249. procedure xControlDecoration.makeActive;
  250.     begin
  251.         if theControl <> nil then
  252.             if grayedOut then begin
  253.                     grayedOut := false;
  254.                     wantsClick := true;
  255.                     if (itsWindow <> nil) & (itsWindow.theWindow <> nil) & (itsWindow.theWindow = FrontWindow) then
  256.                         HiliteControl(theControl, 0);
  257.                 end;
  258.     end;
  259.  
  260. procedure xControlDecoration.init;
  261.     var
  262.         crs: cursHandle;
  263.     begin
  264.         inherited init;
  265.         theControl := nil;
  266.         trueWidth := 1;
  267.         trueHeight := 1;
  268.         wantsClick := true;
  269.         crs := GetCursor(129);
  270.         if crs <> nil then
  271.             useCursor(crs^^);
  272.     end;
  273.  
  274. procedure xControlDecoration.kill;
  275.     begin
  276.         if theControl <> nil then
  277.             disposeControl(theControl);
  278.         inherited kill;
  279.     end;
  280.  
  281. procedure xControlDecoration.doActivate (active: boolean);
  282.     begin
  283.         if theControl <> nil then
  284.             if active then begin
  285.                     if not grayedOut then
  286.                         HiliteControl(theControl, 0);
  287.                 end
  288.             else
  289.                 HiliteControl(theControl, 255);
  290.     end;
  291.  
  292. procedure xControlDecoration.adjustSize;
  293.     var
  294.         savePort: GrafPtr;
  295.     begin
  296.         inherited adjustSize;
  297.         if drawRect.right < drawRect.left + trueWidth then
  298.             drawRect.right := drawRect.left + trueWidth;
  299.         if drawRect.bottom < drawRect.top + trueHeight then
  300.             drawRect.bottom := drawRect.top + trueHeight;
  301.         if (itsWindow <> nil) & (itsWindow.theWindow <> nil) then begin
  302.                 GetPort(savePort);
  303.                 SetPort(itsWindow.theWindow);
  304.                 InvalRect(clickRect);
  305.                 InvalRect(drawRect);
  306.                 SetPort(savePort);
  307.             end;
  308.         clickRect := drawRect;
  309.         if theControl <> nil then begin
  310.                 theControl^^.contrlRect := drawRect;
  311.             end;
  312.     end;
  313.  
  314. procedure xControlDecoration.show;
  315.     begin
  316.         inherited show;
  317.         if theControl <> nil then
  318.             ShowControl(theControl);
  319.     end;
  320.  
  321. procedure xControlDecoration.hide;
  322.     begin
  323.         inherited hide;
  324.         if theControl <> nil then
  325.             HideControl(theControl);
  326.     end;
  327.  
  328.     type
  329.         stringList = array[1..10] of string;
  330.  
  331. procedure SubdivideName (var name: string;
  332.                                 var nameList: stringList;
  333.                                 var ct: integer;
  334.                                 Win: WindowPtr;
  335.                                 var width, height: integer);
  336.     var
  337.         savePort: GrafPTr;
  338.         saveFont: integer;
  339.         saveSize: integer;
  340.         saveFace: style;
  341.         i: integer;
  342.         info: fontInfo;
  343.     begin
  344.         if length(name) = 0 then begin
  345.                 ct := 0;
  346.                 width := 0;
  347.                 height := 0;
  348.                 EXIT(SubdivideName);
  349.             end;
  350.         GetPort(savePort);
  351.         SetPort(win);
  352.         saveFont := win^.txFont;
  353.         saveSize := win^.txSize;
  354.         saveFace := win^.txFace;
  355.         TextFont(systemFont);
  356.         TextSize(12);
  357.         TextFace([]);
  358.         for i := 1 to 10 do
  359.             nameList[i] := '';
  360.         ct := 1;
  361.         i := 1;
  362.         while i <= length(name) do begin
  363.                 if name[i] = '\' then begin
  364.                         name[i] := chr(13);
  365.                         if ct = 10 then
  366.                             i := length(name)
  367.                         else
  368.                             ct := ct + 1;
  369.                     end
  370.                 else
  371.                     nameList[ct] := Concat(nameList[ct], name[i]);
  372.                 i := i + 1;
  373.             end;
  374.         width := 0;
  375.         for i := 1 to ct do
  376.             if StringWidth(nameList[i]) > width then
  377.                 width := StringWidth(nameList[i]);
  378.         GetFontInfo(info);
  379.         height := ct * (info.ascent + info.descent + info.leading);
  380.         TextFace(saveFace);
  381.         TextFont(saveFont);
  382.         TextSize(saveSize);
  383.         SetPort(savePort);
  384.     end;
  385.  
  386. procedure xButton.SetUp (win: xWindow;
  387.                                 name: string;
  388.                                 theLeft, theTop, theWidth, theHeight: integer);
  389.     var
  390.         dh, dv: integer;
  391.         junkArray: stringList;
  392.         junkCount: integer;
  393.     begin
  394.         init;
  395.         if (win = nil) | (win.theWindow = nil) then
  396.             EXIT(SetUp);
  397.         SubDivideName(name, junkArray, junkCount, win.theWindow, dh, dv);
  398.         trueWidth := dh + 20;
  399.         trueHeight := dv + 4;
  400.         install(win, theLeft, theTop, theWidth, theHeight);  { size will be adjusted }
  401.         theControl := NewControl(win.theWindow, clickRect, name, true, 0, 0, 1, pushButProc, 0);
  402.     end;
  403.  
  404. procedure xButton.HandleClick;
  405.     begin
  406.         Sysbeep(5);
  407.     end;
  408.  
  409. procedure xButton.Press;
  410.     var
  411.         junk: longint;
  412.     begin
  413.         if (not grayedOut) & (itsWindow.theWindow <> nil) & (itsWindow.theWindow = FrontWindow) then begin
  414.                 HiliteControl(theControl, 1);
  415.                 Delay(7, junk);
  416.                 HiliteControl(theControl, 0);
  417.             end;
  418.         HandleClick;
  419.     end;
  420.  
  421. procedure xButton.SetName (name: string);
  422.     var
  423.         junkArray: stringList;
  424.         junkCount: integer;
  425.         dh, dv: integer;
  426.         changeSize: boolean;
  427.     begin
  428.         if (theControl = nil) | (itsWindow = nil) | (itsWindow.theWindow = nil) then
  429.             EXIT(setName);
  430.         SubDivideName(name, junkArray, junkCount, itsWindow.theWindow, dh, dv);
  431.         changeSize := false;
  432.         if (dh + 2 > drawRect.right - drawRect.left) then begin
  433.                 truewidth := dh + 20;
  434.                 changeSize := true;
  435.             end;
  436.         if (dv + 2 > drawRect.bottom - drawRect.top) then begin
  437.                 trueHeight := dv + 4;
  438.                 changeSize := true;
  439.             end;
  440.         if changeSize then
  441.             adjustSize;
  442.         SetCTitle(theControl, name);
  443.     end;
  444.  
  445. procedure xButton.doClick (localPt: point;
  446.                                 modifiers: longint);
  447.     begin
  448.         if TrackControl(theControl, localPt, nil) <> 0 then
  449.             HandleClick;
  450.     end;
  451.  
  452. procedure xDefaultButton.init;
  453.     begin
  454.         inherited init;
  455.         wantsCR := true;
  456.     end;
  457.  
  458. procedure xDefaultButton.adjustSize;
  459.     begin
  460.         inherited adjustSize;
  461.         InsetRect(drawRect, -4, -4);
  462.     end;
  463.  
  464. procedure xDefaultButton.doCr (ch: char);
  465.     begin
  466.         press;
  467.     end;
  468.  
  469. procedure xDefaultButton.doDraw;
  470.     var
  471.         saveSize: point;
  472.     begin
  473.         inherited doDraw;
  474.         saveSize := itsWindow.theWindow^.pnSize;
  475.         PenSize(3, 3);
  476.         FrameRoundRect(drawRect, 24, 24);
  477.         PenSize(saveSize.h, saveSize.v);
  478.     end;
  479.  
  480. procedure xCheckBox.SetUp (win: xWindow;
  481.                                 name: string;
  482.                                 theLeft, theTop: integer);
  483.     var
  484.         dh, dv: integer;
  485.         junkArray: stringList;
  486.         junkCount: integer;
  487.     begin
  488.         init;
  489.         if (win = nil) | (win.theWindow = nil) then
  490.             EXIT(SetUp);
  491.         SubDivideName(name, junkArray, junkCount, win.theWindow, dh, dv);
  492.         trueWidth := dh + 20;
  493.         trueHeight := dv;
  494.         install(win, theLeft, theTop, trueWidth, trueHeight);
  495.         theControl := NewControl(win.theWindow, clickRect, name, true, 0, 0, 1, checkBoxProc, 0);
  496.     end;
  497.  
  498. procedure xCheckBox.check;
  499.     begin
  500.         if theControl <> nil then
  501.             SetCtlValue(theControl, 1);
  502.     end;
  503.  
  504. procedure xCheckBox.unCheck;
  505.     begin
  506.         if theControl <> nil then
  507.             SetCtlValue(theControl, 0);
  508.     end;
  509.  
  510. function xCheckBox.checked: boolean;
  511.     begin
  512.         if theControl <> nil then
  513.             checked := (GetCtlValue(theControl) = 1);
  514.     end;
  515.  
  516. procedure xCheckBox.HandleClick;
  517.     begin
  518.     end;
  519.  
  520. procedure xCheckBox.doClick (localPt: point;
  521.                                 modifiers: longint);
  522.     begin
  523.         if (theControl <> nil) & (TrackControl(theControl, localPt, nil) <> 0) then begin
  524.                 if checked then
  525.                     uncheck
  526.                 else
  527.                     check;
  528.                 HandleClick
  529.             end;
  530.     end;
  531.  
  532. procedure xRadioButton.SetUp (win: xWindow;
  533.                                 name: string;
  534.                                 theLeft, theTop: integer);
  535.     var
  536.         dh, dv: integer;
  537.         junkArray: stringList;
  538.         junkCount: integer;
  539.     begin
  540.         init;
  541.         if (win = nil) | (win.theWindow = nil) then
  542.             EXIT(SetUp);
  543.         SubDivideName(name, junkArray, junkCount, win.theWindow, dh, dv);
  544.         trueWidth := dh + 20;
  545.         trueHeight := dv;
  546.         install(win, theLeft, theTop, trueWidth, trueHeight);
  547.         theControl := NewControl(win.theWindow, clickRect, name, true, 0, 0, 1, radioButProc, 0);
  548.         itsGroup := nil;
  549.     end;
  550.  
  551. procedure xRadioButton.doClick (localPt: point;
  552.                                 modifiers: longint);
  553.     begin
  554.         if (theControl <> nil) & (TrackControl(theControl, localPt, nil) <> 0) then begin
  555.                 if itsGroup <> nil then begin
  556.                         if not checked then
  557.                             itsGroup.select(numInGroup);
  558.                     end
  559.                 else begin
  560.                         if checked then
  561.                             uncheck
  562.                         else
  563.                             check;
  564.                         HandleClick
  565.                     end;
  566.             end;
  567.     end;
  568.  
  569. procedure xRadioGroup.SetUp (win: xWindow;
  570.                                 name: string;
  571.                                 theLeft, theTop: integer);
  572.     var
  573.         nameList: stringList;
  574.         nameCt: integer;
  575.         dh, dv: integer;
  576.         i: integer;
  577.         rb: xRadioButton;
  578.     begin
  579.         if (win = nil) | (win.theWindow = nil) then
  580.             EXIT(Setup);
  581.         SubdivideName(name, nameList, nameCt, win.theWindow, dh, dv);
  582.         if nameCt = 0 then
  583.             EXIT(setUp);
  584.         buttonCount := nameCt;
  585.         dv := dv div buttonCount;
  586.         for i := 1 to buttonCount do begin
  587.                 new(rb);
  588.                 rb.setUp(win, nameList[i], theLeft, theTop);
  589.                 rb.itsGroup := self;
  590.                 rb.numInGroup := i;
  591.                 theButtons[i] := rb;
  592.                 theTop := theTop + dv;
  593.             end;
  594.         selected := 1;
  595.         theButtons[1].check
  596.     end;
  597.  
  598. procedure xRadioGroup.select (buttonNum: integer);
  599.     begin
  600.         if (buttonNum > 0) & (buttonNum <= buttonCount) & (buttonNum <> selected) then begin
  601.                 theButtons[selected].uncheck;
  602.                 theButtons[buttonNum].check;
  603.                 selected := buttonNum;
  604.                 HandleChangeOfSelection
  605.             end;
  606.     end;
  607.  
  608. function xRadioGroup.selectedButton: integer;
  609.     begin
  610.         selectedButton := selected;
  611.     end;
  612.  
  613. procedure xRadioGroup.HandleChangeOfSelection;
  614.     begin
  615.     end;
  616.  
  617. procedure xRadioGroup.hide;
  618.     var
  619.         i: integer;
  620.     begin
  621.         for i := 1 to buttonCount do
  622.             theButtons[i].hide;
  623.     end;
  624.  
  625. procedure xRadioGroup.show;
  626.     var
  627.         i: integer;
  628.     begin
  629.         for i := 1 to buttonCount do
  630.             theButtons[i].show;
  631.     end;
  632.  
  633. procedure xScrollBar.SetUp (win: xWindow;
  634.                                 theLeft, theTop, theWidth, theHeight: integer);
  635.     begin
  636.         init;
  637.         if (win = nil) | (win.theWindow = nil) then
  638.             EXIT(SetUp);
  639.         trueWidth := 10;
  640.         trueHeight := 10;
  641.         linesPerPage := 1;
  642.         grayedOut := false;
  643.         savedMax := -1;
  644.         install(win, theLeft, theTop, theWidth, theHeight);  { size will be adjusted }
  645.         theControl := NewControl(win.theWindow, clickRect, '', true, 0, 0, 0, scrollBarProc, longint(self));
  646.     end;
  647.  
  648. procedure xScrollBar.adjustSize;
  649.     var
  650.         w, h: integer;
  651.         savePort: GrafPtr;
  652.     begin
  653.         if (itsWindow <> nil) & (itsWindow.theWindow <> nil) then begin
  654.                 if left < 0 then
  655.                     drawRect.left := itsWindow.theWindow^.portRect.right + left
  656.                 else
  657.                     drawRect.left := left;
  658.                 if top < 0 then
  659.                     drawRect.top := itsWindow.theWindow^.portRect.bottom + top
  660.                 else
  661.                     drawRect.top := top;
  662.                 if height <= 0 then
  663.                     drawRect.bottom := itsWindow.theWindow^.portRect.bottom + height
  664.                 else
  665.                     drawRect.bottom := drawRect.top + height;
  666.                 if width <= 0 then
  667.                     drawRect.right := itsWindow.theWindow^.portRect.right + width
  668.                 else
  669.                     drawRect.right := drawRect.left + width;
  670.                 if (itsWindow <> nil) & (itsWindow.theWindow <> nil) then begin
  671.                         GetPort(savePort);
  672.                         SetPort(itsWindow.theWindow);
  673.                         InvalRect(clickRect);
  674.                         InvalRect(drawRect);
  675.                         SetPort(savePort);
  676.                     end;
  677.                 clickRect := drawRect;
  678.                 w := clickRect.right - clickRect.left;
  679.                 h := clickRect.bottom - clickRect.top;
  680.                 if (w < 40) & (h < 40) then begin
  681.                         if w > h then
  682.                             w := 40
  683.                         else
  684.                             h := 40
  685.                     end;
  686.                 if (w > h) then begin
  687.                         if (h > w div 4) | (h < 10) then
  688.                             h := w div 4
  689.                     end
  690.                 else begin
  691.                         if (w > h div 4) | (w < 10) then
  692.                             w := h div 4
  693.                     end;
  694.                 clickRect.right := clickRect.left + w;
  695.                 clickRect.bottom := clickRect.top + h;
  696.                 drawRect := clickRect;
  697.                 if theControl <> nil then begin
  698.                         theControl^^.contrlRect := drawRect;
  699.                     end;
  700.             end;
  701.     end;
  702.  
  703. procedure xScrollBar.SetMax (newMax: integer);
  704.     begin
  705.         if theControl <> nil then begin
  706.                 if savedMax >= 0 then
  707.                     savedMax := newMax
  708.                 else begin
  709.                         SetCtlMax(theControl, newMax);
  710.                     end;
  711.             end;
  712.     end;
  713.  
  714. procedure xScrollBar.SetVal (newVal: integer);
  715.     begin
  716.         if theControl <> nil then
  717.             if savedMax >= 0 then
  718.                 savedVal := newVal
  719.             else
  720.                 SetCtlValue(theControl, newVal);
  721.     end;
  722.  
  723. function xScrollBar.GetVal: integer;
  724.     begin
  725.         if theControl <> nil then
  726.             GetVal := GetCtlValue(theControl);
  727.     end;
  728.  
  729. function xScrollBar.GetMax: integer;
  730.     begin
  731.         if theControl <> nil then
  732.             GetMax := GetCtlMax(theControl);
  733.     end;
  734.  
  735. procedure xScrollBar.makeActive;
  736.     begin
  737.         if savedMax >= 0 then begin
  738.                 SetCtlMax(theControl, savedMax);
  739.                 SetCtlValue(theControl, savedVal);
  740.                 if savedMax > 0 then begin
  741.                         grayedOut := false;
  742.                         wantsClick := true;
  743.                     end;
  744.                 savedMax := -1;
  745.                 if (itsWindow <> nil) & (itsWindow.theWindow <> nil) & (itsWindow.theWindow = FrontWindow) then
  746.                     HiliteControl(theControl, 0);
  747.             end;
  748.     end;
  749.  
  750. procedure xScrollBar.makeInactive;
  751.     begin
  752.         if (theControl <> nil) & (savedMax = -1) then begin
  753.                 savedMax := GetCtlMax(theControl);
  754.                 savedVal := GetCtlValue(theControl);
  755.                 SetCtlMax(theControl, 0);
  756.                 grayedOut := true;
  757.                 wantsClick := false;
  758.                 HiliteControl(theControl, 255);
  759.             end;
  760.     end;
  761.  
  762. procedure xScrollBar.SetLinesPerPage (lines: integer);
  763.     begin
  764.         if lines < 1 then
  765.             linesPerPage := 1
  766.         else
  767.             LinesPerPage := lines;
  768.     end;
  769.  
  770. procedure xScrollBar.HandleScroll (changeInVal: integer);
  771.     begin
  772.     end;
  773.  
  774. procedure continuousScroll (ctl: ControlHandle;
  775.                                 partCode: integer);
  776.     var
  777.         dec: xScrollBar;
  778.         lines: integer;
  779.         val: integer;
  780.         max: integer;
  781.     begin
  782.         val := getCtlValue(ctl);
  783.         max := getCtlMax(ctl);
  784.         dec := xScrollBar(ctl^^.ContrlRfCon);
  785.         case partCode of
  786.             inDownButton: 
  787.                 lines := 1;
  788.             inUpButton: 
  789.                 lines := -1;
  790.             inPageDown: 
  791.                 lines := dec.LinesPerPage;
  792.             inPageUp: 
  793.                 lines := -dec.LinesPerPage;
  794.             otherwise
  795.                 EXIT(ContinuousScroll);
  796.         end;
  797.         if val + lines < 0 then
  798.             lines := -val
  799.         else if val + lines > max then
  800.             lines := max - val;
  801.         if lines <> 0 then begin
  802.                 SetCtlValue(ctl, val + lines);
  803.                 dec.HandleScroll(lines)
  804.             end;
  805.     end;
  806.  
  807.  
  808.  
  809. procedure xScrollBar.doClick (localPt: point;
  810.                                 modifiers: longint);
  811.     var
  812.         part: integer;
  813.         ctl: ControlHandle;
  814.         oldVal: integer;
  815.     begin
  816.         part := FindControl(localPt, itsWindow.theWindow, ctl);
  817.         if (part = 0) | (ctl <> theControl) then
  818.             EXIT(doClick);
  819.         if part in [inUpButton, inDownButton, inPageUp, inPageDown] then
  820.             part := TrackControl(ctl, localPt, @continuousScroll)
  821.         else if part = inThumb then begin
  822.                 oldVal := GetCtlValue(ctl);
  823.                 part := TrackControl(ctl, localPt, nil);
  824.                 if (part = inThumb) & (oldVal <> GetCtlValue(ctl)) then
  825.                     HandleScroll(GetCtlValue(theControl) - oldVal)
  826.             end;
  827.     end;
  828.  
  829.  
  830. procedure xEmptyButton.SetUp (win: xWindow;
  831.                                 theLeft, theRight, theWidth, theHeight: integer);
  832.     var
  833.         crs: CursHandle;
  834.     begin
  835.         init;
  836.         wantsClick := true;
  837.         crs := GetCursor(129);
  838.         if crs <> nil then
  839.             useCursor(crs^^);
  840.         install(win, theLeft, theRight, theWidth, theHeight);
  841.     end;
  842.  
  843. procedure xEmptyButton.HandleClick;
  844.     begin
  845.         SysBeep(5);
  846.     end;
  847.  
  848. procedure xEmptyButton.Press;
  849.     var
  850.         junk: longint;
  851.         savePort: GrafPtr;
  852.     begin
  853.         if (visible) & (itsWindow.theWindow <> nil) & (itsWindow.theWindow = FrontWindow) then begin
  854.                 GetPort(savePort);
  855.                 SetPort(itsWindow.theWindow);
  856.                 InvertRect(drawRect);
  857.                 Delay(7, junk);
  858.                 InvertRect(drawRect);
  859.                 SetPort(savePort);
  860.             end;
  861.         HandleClick;
  862.     end;
  863.  
  864. procedure xEmptyButton.doClick (localPt: point;
  865.                                 modifiers: longint);
  866.     var
  867.         inside: boolean;
  868.         pt: point;
  869.     begin
  870.         inside := false;
  871.         while StillDown do begin
  872.                 GetMouse(pt);
  873.                 if PtInRect(pt, drawRect) then begin
  874.                         if not inside then begin
  875.                                 inside := true;
  876.                                 InvertRect(drawRect);
  877.                             end;
  878.                     end
  879.                 else begin
  880.                         if inside then begin
  881.                                 inside := false;
  882.                                 InvertRect(drawRect);
  883.                             end;
  884.                     end;
  885.             end;
  886.         if inside then begin
  887.                 InvertRect(drawRect);
  888.                 HandleClick;
  889.             end;
  890.     end;
  891.  
  892. procedure xFramedEmptyButton.doDraw;
  893.     var
  894.         savePen: point;
  895.     begin
  896.         savePen := itsWindow.theWindow^.pnSize;
  897.         PenSize(1, 1);
  898.         FrameRect(drawRect);
  899.         PenSize(savePen.h, savePen.v);
  900.     end;
  901.  
  902. end.